package com.wan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wan.common.BaseContext;
import com.wan.common.CustomException;
import com.wan.dto.OrdersDto;
import com.wan.mapper.OrderMapper;
import com.wan.pojo.*;
import com.wan.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements OrderService {

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private UserService userService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private OrderDetailService orderDetailService;
    /**
     * 用户下单
     * @param orders
     * @return
     */
    @Override
    @Transactional
    public void submit(Orders orders) {
        // 获取当前用户id
        Long userId = BaseContext.getCurrentId();

        // 查询当前用户购物车数据
        LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<>();
        // 添加用户id条件
        wrapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(wrapper);
        // 根据用户id查询用户信息
        User user = userService.getById(userId);
        // 根据地址id查询当前用户地址
        Long addressBookId = orders.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        if (addressBook == null){
            throw new CustomException("用户地址有误，不能下单！");
        }
        long orderId = IdWorker.getId(); // 订单号

        AtomicInteger amount = new AtomicInteger(0); // 有原子操作  这个类型可以保证就算在多线程的情况下也不会计算出错
        // 这边在变量购物车里面的数据
        for (ShoppingCart cart : shoppingCarts) {
            //   addAndGet 相当于+=    multiply 相当于乘   BigDecimal  类型   intValue输出int类型数据
            amount.addAndGet(cart.getAmount().multiply(new BigDecimal(cart.getNumber())).intValue());
        }
        log.info("总金额：{}",amount);
        // 设置各种值
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setStatus(2);
        orders.setAmount(new BigDecimal(amount.get()));//总金额
        orders.setUserId(userId);
        orders.setNumber(String.valueOf(orderId));
        orders.setUserName(user.getName());
        orders.setConsignee(addressBook.getConsignee());
        orders.setPhone(addressBook.getPhone());
        // 这边做了三元判断  分别判断省、市、区 最后拼接上详细地址
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
        // 向订单表插入一条数据
        this.save(orders);

        List<OrderDetail> orderDetails = shoppingCarts.stream().map((item)->{
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orders.getId());
            orderDetail.setNumber(item.getNumber());
            orderDetail.setDishFlavor(item.getDishFlavor());
            orderDetail.setDishId(item.getDishId());
            orderDetail.setSetmealId(item.getSetmealId());
            orderDetail.setName(item.getName());
            orderDetail.setImage(item.getImage());
            orderDetail.setAmount(item.getAmount());
            return orderDetail;
        }).collect(Collectors.toList());
        // 向订单明细表插入数据，多条数据
        orderDetailService.saveBatch(orderDetails);
        // 清空当前用户购物车数据
        shoppingCartService.remove(wrapper);
    }

    /**
     * 用户查询订单
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    @Transactional
    public Page<OrdersDto> getOrdersInfo(int page, int pageSize) {
        Page<Orders> pageInfo = new Page<>(page,pageSize);
        Page<OrdersDto> ordersDtoPage = new Page<>();
        // 获取当前用户id
        Long userId = BaseContext.getCurrentId();
        // 根据用户id查询用户表
        User user = userService.getById(userId);

        log.info("当前用户详细信息：{}",user.toString());
        // 构造条件构造器
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        // 条件为等于用户id
        queryWrapper.eq(Orders::getUserId,userId);
        // 根据用户id查询用户订单
        this.page(pageInfo, queryWrapper);
        log.info("分页数据：{}",pageInfo.getRecords());
        // 对象拷贝
        BeanUtils.copyProperties(pageInfo,ordersDtoPage,"records");
        List<Orders> records = pageInfo.getRecords();
        // 根据订单id查询订单详细
        List<OrdersDto> collect = records.stream().map((item) -> {
            OrdersDto ordersDto = new OrdersDto();
            LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OrderDetail::getOrderId, item.getId());
            // 调用sql语句查询 查询订单详细表
            List<OrderDetail> orderDetails = orderDetailService.list(wrapper);
            ordersDto.setOrderDetails(orderDetails);
            // 把金额取出来赋值到返回类中
            ordersDto.setAmount(item.getAmount());
            return ordersDto;
        }).collect(Collectors.toList());
        // 把查询出来的数据 设置到ordersDtoPage.setRecords中
        ordersDtoPage.setRecords(collect);
        return ordersDtoPage;
    }
    /**
     * 后端订单详细信息查询
     * @param page
     * @param pageSize
     * @param number
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    @Transactional
    public Page<OrdersDto> serverPage(int page, int pageSize, String number, String beginTime, String endTime) {
        Page<Orders> pageInfo = new Page<>(page,pageSize);
        Page<OrdersDto> ordersDtoPage = new Page<>();
        // 构造条件构造器
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        // 添加订单号条件  但是先判断了是否为空
        queryWrapper.like(StringUtils.isNotEmpty(number),Orders::getNumber,number);
        // 添加查询时间条件  设置需要大于的时间
        queryWrapper.ge(StringUtils.isNotEmpty(beginTime),Orders::getOrderTime,beginTime);
        // 设置最大时间条件
        queryWrapper.le(StringUtils.isNotEmpty(endTime),Orders::getOrderTime,endTime);
        // 调用分页查询
        Page<Orders> ordersPage = this.page(pageInfo,queryWrapper);
        // 数据拷贝
        BeanUtils.copyProperties(pageInfo,ordersDtoPage,"records");
        // 获取存储在pageInfo.getRecords里面的数据并且拼接好完整地址
        List<Orders> records = pageInfo.getRecords();
        List<OrdersDto> collect = records.stream().map((item) -> {
            // 创建orderDto对象  用于接收每一次数据进行返回
            OrdersDto ordersDto = new OrdersDto();
            // 设置订单号
            ordersDto.setNumber(item.getNumber());
            // 设置状态
            ordersDto.setStatus(item.getStatus());
            // 将消费的金额给到dto中
            ordersDto.setAmount(item.getAmount());
            // 下单时间
            ordersDto.setOrderTime(item.getOrderTime());
            // 手机号
            ordersDto.setPhone(item.getPhone());
            // 通过订单表中的用户id查询用户表
            User user = userService.getById(item.getUserId());
            // 设置用户名
            ordersDto.setUserName(user.getName());
            // 获取每一项订单的id
            Long itemId = item.getId();
            LambdaQueryWrapper<OrderDetail> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OrderDetail::getOrderId, itemId);
            // 查询订单详细信息
            List<OrderDetail> orderDetails = orderDetailService.list(wrapper);
            // 将查询的数据存入需要返回的dto类中
            ordersDto.setOrderDetails(orderDetails);
            // 查询收货地址信息
            // 调用sql语句查询地址表
            AddressBook addressBook = addressBookService.getById(item.getAddressBookId());
            // 这边做了三元判断  分别判断省、市、区 最后拼接上详细地址
            ordersDto.setAddress(
                    (addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                            + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                            + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                            + (addressBook.getDetail() == null ? "" : addressBook.getDetail())
            );
            return ordersDto;
        }).collect(Collectors.toList());
        // 将最终的结果给到返回的dto上
        ordersDtoPage.setRecords(collect);
        return ordersDtoPage;
    }
}
